package com.example.openim.service.impl;

import com.example.openim.domain.PersonData;
import com.example.openim.dto.PersonDataDto;
import com.example.openim.service.UserQueryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.*;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * @description:
 * @author: ZhangHuixin
 * @created: 2025-11-04 09:58:58
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class UserQueryServiceImpl implements UserQueryService {

    private final MongoTemplate mongoTemplate;

    @Override
    public List<PersonData> findUsers(String zbmId) {

        // 1. 过滤条件：ZBMID + (ZRYDE null/empty) + (BLOCK null/empty)
        Criteria filterCriteria = Criteria.where("ZBMID").is(zbmId)
                .andOperator(
                        Criteria.where("ZRYDE").in(null, ""),   // null 或 ""
                        Criteria.where("BLOCK").in(null, "")    // null 或 ""
                );

        // 1. $lookup：关联 credential 表
        LookupOperation lookup = Aggregation.lookup(
                "credential",           // 从表集合名
                "ZSJHM",               // 主表字段（人员编码）
                "account",              // 从表字段（匹配）
                "credentialInfo"        // 临时数组字段
        );

        // 2. $unwind：展开（保留无匹配的记录）
        UnwindOperation unwind = Aggregation.unwind("$credentialInfo", true);

        // 3. $addFields / $set：把 user_id 赋值给 userid
        AddFieldsOperation setUserId = Aggregation.addFields()
                .addFieldWithValue("userid",
                        new org.bson.Document("$ifNull",
                                java.util.Arrays.asList("$credentialInfo.user_id", "$userid")
                        )
                )
                .build();

        // 4. $project：返回最终字段（去掉临时字段）
        ProjectionOperation project = Aggregation.project()
                .andInclude(
                        "ID", "ZRYXM", "ZDNAME", "ZBMID", "ZXZPER", "ZRYPX",
                        "ZZGANG", "ZXB", "ZSJHM", "ZDZYJ", "ZRYDE", "ZZWJB", "BLOCK"
                )
                .and("userid").as("USERID");  // 包含填充后的 userid

        // 5. 组装聚合管道
        Aggregation aggregation = Aggregation.newAggregation(
                Aggregation.match(filterCriteria),
                lookup,
                unwind,
                setUserId,
                project
        );

        // 6. 执行查询，返回 PersonData 列表

        List<PersonData> personData = mongoTemplate
                .aggregate(aggregation, "person_data", PersonData.class)  // 集合名
                .getMappedResults();

        personData.forEach(item -> {
            item.setZsjhm(item.getZsjhm().replaceFirst("^\\+\\d+\\s*", ""));
        });
        return personData;
    }

    /**
     * Method to query person data by phone number
     *
     * @param phone The phone number to search for
     * @return PersonDataDto object containing the person's data, or null if not found
     */
    @Override
    public PersonDataDto queryByPhone(String phone, String userId) {

        phone = String.format("+86 %s", StringUtils.isNotBlank(phone) ? phone.trim() : phone);
        if (!StringUtils.isEmpty(userId)) {
            Query userQuery = new Query(Criteria.where("user_id").is(userId));
            Map credential = mongoTemplate.findOne(userQuery, Map.class, "credential");
            if (!CollectionUtils.isEmpty(credential)) {
                phone = (String) credential.get("account");
            }

        }
        Aggregation agg = Aggregation.newAggregation(
                // 通过手机号查询
                Aggregation.match(
                        new Criteria().orOperator(
                                Criteria.where("ZSJHM").is(phone)
                        )
                ),

                // 2. 关联当前组织
                Aggregation.lookup("org_data", "ZBMID", "ZXZORG", "orgInfo"),
                Aggregation.unwind("orgInfo", true),

                // 3. 关联上级组织
                Aggregation.lookup("org_data", "orgInfo.ZSJBMID", "ZXZORG", "parentOrg"),
                Aggregation.unwind("parentOrg", true),

                // 4. 关联 credential，通过 person_data.ZSJHM -> credential.account
                Aggregation.lookup("credential", "ZSJHM", "account", "credentialInfo"),
                Aggregation.unwind("credentialInfo", true),

                // 5. 关联 user，通过 credentialInfo.user_id -> user.user_id
                Aggregation.lookup("user", "credentialInfo.user_id", "user_id", "userInfo"),
                Aggregation.unwind("userInfo", true),

                // 6. 显式映射所有需要返回的字段
                Aggregation.project("id", "ZRYXM", "ZDNAME", "ZBMID", "ZXZPER", "ZRYPX", "ZZGANG", "ZXB", "ZSJHM", "ZDZYJ", "ZRYDE", "ZZWJB", "BLOCK", "USERID")
                        .and("orgInfo.ZBMTX").as("orgName")
                        .and("parentOrg.ZBMTX").as("parentOrgName")
                        .and("credentialInfo.user_id").as("USERID")
                        .and("userInfo.face_url").as("faceUrl"),
                Aggregation.limit(1)
        );


        PersonDataDto personData = mongoTemplate
                .aggregate(agg, "person_data", PersonDataDto.class)
                .getUniqueMappedResult();

        // 添加以下代码来去除 ZSJHM 字段中的 "+86 " 前缀
        if (personData != null && personData.getZsjhm() != null) {
            personData.setZsjhm(personData.getZsjhm().replaceFirst("^\\+86\\s*", ""));
        }
        return personData;


    }


    /**
     * @param search
     * @return
     */
    @Override
    public List<PersonDataDto> querySearch(String search) {
        Aggregation agg = Aggregation.newAggregation(
                // 1. 姓名 or 手机号模糊查询
                Aggregation.match(
                        new Criteria().orOperator(
                                Criteria.where("ZRYXM").regex(search, "i"),
                                Criteria.where("ZSJHM").regex(search, "i")
                        )
                ),

                // 2. 关联当前组织
                Aggregation.lookup("org_data", "ZBMID", "ZXZORG", "orgInfo"),
                Aggregation.unwind("orgInfo", true),

                // 3. 关联上级组织
                Aggregation.lookup("org_data", "orgInfo.ZSJBMID", "ZXZORG", "parentOrg"),
                Aggregation.unwind("parentOrg", true),

                // 4. 关联 credential，通过 person_data.ZSJHM -> credential.account
                Aggregation.lookup("credential", "ZSJHM", "account", "credentialInfo"),
                Aggregation.unwind("credentialInfo", true),

                // 5. 关联 user，通过 credentialInfo.user_id -> user.user_id
                Aggregation.lookup("user", "credentialInfo.user_id", "user_id", "userInfo"),
                Aggregation.unwind("userInfo", true),

                // 6. 显式映射所有需要返回的字段
                Aggregation.project("id", "ZRYXM", "ZDNAME", "ZBMID", "ZXZPER", "ZRYPX", "ZZGANG", "ZXB", "ZSJHM", "ZDZYJ", "ZRYDE", "ZZWJB", "BLOCK", "USERID")
                        .and("orgInfo.ZBMTX").as("orgName")
                        .and("parentOrg.ZBMTX").as("parentOrgName")
                        .and("credentialInfo.user_id").as("USERID")
                        .and("userInfo.face_url").as("faceUrl")
        );

        List<PersonDataDto> result = mongoTemplate
                .aggregate(agg, "person_data", PersonDataDto.class)
                .getMappedResults();

        return result;


    }
}
